1 using System.Collections;
2 using ProceduralToolkit.Examples.UI;
3 using UnityEngine;
4 using UnityEngine.UI;
5
6 namespace ProceduralToolkit.Examples
7 {
8 public class MazeGeneratorConfigurator : ConfiguratorBase
9 {
10 public RectTransform leftPanel;
11 public ToggleGroup algorithmsGroup;
12 public RawImage mazeImage;
13 [Space]
14 public MazeGenerator.Config config = new MazeGenerator.Config();
15 public bool useGradient = true;
16
17 private const float gradientSaturation = 0.7f;
18 private const float gradientSaturationOffset = 0.1f;
19 private const float gradientValue = 0.7f;
20 private const float gradientValueOffset = 0.1f;
21 private const float gradientLength = 30;
22
23 private Texture2D texture;
24 private MazeGenerator mazeGenerator;
25 private ColorHSV mainColor;
26
27 private void Awake()
28 {
29 config.drawEdge = DrawEdge;
30
31 texture = new Texture2D(config.mazeWidth, config.mazeHeight, TextureFormat.ARGB32, false, true)
32 {
33 filterMode = FilterMode.Point
34 };
35 mazeImage.texture = texture;
36
37 var header = InstantiateControl<TextControl>(algorithmsGroup.transform.parent);
38 header.Initialize("Generator algorithm");
39 header.transform.SetAsFirstSibling();
40
41 InstantiateToggle(MazeGenerator.Algorithm.RandomTraversal, "Random traversal");
42 InstantiateToggle(MazeGenerator.Algorithm.RandomDepthFirstTraversal, "Random depth-first traversal");
43 InstantiateToggle(MazeGenerator.Algorithm.RandomBreadthFirstTraversal, "Random breadth-first traversal");
44
45 InstantiateControl<SliderControl>(leftPanel).Initialize("Cell size", 1, 10, config.cellSize, value =>
46 {
47 config.cellSize = value;
48 Generate();
49 });
50
51 InstantiateControl<SliderControl>(leftPanel).Initialize("Wall size", 1, 10, config.wallSize, value =>
52 {
53 config.wallSize = value;
54 Generate();
55 });
56
57 InstantiateControl<ToggleControl>(leftPanel).Initialize("Use gradient", useGradient, value =>
58 {
59 useGradient = value;
60 Generate();
61 });
62
63 InstantiateControl<ButtonControl>(leftPanel).Initialize("Generate new maze", Generate);
64
65 Generate();
66 SetupSkyboxAndPalette();
67 }
68
69 private void Update()
70 {
71 UpdateSkybox();
72 }
73
74 private void Generate()
75 {
76 StopAllCoroutines();
77
78 texture.Clear(Color.black);
79 texture.Apply();
80
81 mazeGenerator = new MazeGenerator(config);
82
83 GeneratePalette();
84 mainColor = GetMainColorHSV();
85
86 StartCoroutine(GenerateCoroutine());
87 }
88
89 private IEnumerator GenerateCoroutine()
90 {
91 while (mazeGenerator.Generate(steps: 200))
92 {
93 texture.Apply();
94 yield return null;
95 }
96 }
97
98 private void DrawEdge(Edge edge)
99 {
100 int x, y, width, height;
101 if (edge.origin.direction == Directions.Left || edge.origin.direction == Directions.Down)
102 {
103 x = Translate(edge.exit.x);
104 y = Translate(edge.exit.y);
105 }
106 else
107 {
108 x = Translate(edge.origin.x);
109 y = Translate(edge.origin.y);
110 }
111
112 if (edge.origin.direction == Directions.Left || edge.origin.direction == Directions.Right)
113 {
114 width = config.cellSize*2 + config.wallSize;
115 height = config.cellSize;
116 }
117 else
118 {
119 width = config.cellSize;
120 height = config.cellSize*2 + config.wallSize;
121 }
122
123 Color color;
124 if (useGradient)
125 {
126 float gradient01 = Mathf.Repeat(edge.origin.depth/gradientLength, 1);
127 float gradient010 = Mathf.Abs((gradient01 - 0.5f)*2);
128
129 color = GetColor(gradient010);
130 }
131 else
132 {
133 color = GetColor(0.75f);
134 }
135 texture.DrawRect(x, y, width, height, color);
136 }
137
138 private int Translate(int x)
139 {
140 return config.wallSize + x*(config.cellSize + config.wallSize);
141 }
142
143 private Color GetColor(float gradientPosition)
144 {
145 float saturation = gradientPosition*gradientSaturation + gradientSaturationOffset;
146 float value = gradientPosition*gradientValue + gradientValueOffset;
147 return mainColor.WithSV(saturation, value).ToColor();
148 }
149
150 private void InstantiateToggle(MazeGenerator.Algorithm algorithm, string header)
151 {
152 var toggle = InstantiateControl<ToggleControl>(algorithmsGroup.transform);
153 toggle.Initialize(
154 header: header,
155 value: algorithm == config.algorithm,
156 onValueChanged: isOn =>
157 {
158 if (isOn)
159 {
160 config.algorithm = algorithm;
161 Generate();
162 }
163 },
164 toggleGroup: algorithmsGroup);
165 }
166 }
167 }